import base64
import os
import uuid
from typing import List

import cv2
import numpy as np
from flask import request

from configs.global_config import global_config
from controllers.base_controller import BaseController
from insightface_modules.face_feature_extractor import FaceFeatureExtractor
from entity.face_types import (
    BatchExtractFaceFeaturesParam,
    BatchImageResult,
    BatchProcessResult,
)
from utils.api_response_utils import create_error_response, create_success_response
from utils.logger_config import get_logger


class FaceFeatureController(BaseController):
    """人脸特征控制器，处理人脸特征提取相关请求"""

    def __init__(self, import_name):
        """
        初始化控制器

        Args:
            import_name: 导入名称
        """
        # 自己创建和管理FaceFeatureExtractor实例
        self.extractor = FaceFeatureExtractor()
        super().__init__("face_feature", import_name, url_prefix="")
        global_config.initialize()
        print(global_config.raw_config)  # 打印原始配置对象以验证初始化
        self.logger = get_logger()

    def register_routes(self):
        """注册路由"""

        @self.route("/visualize_face_bboxes", methods=["POST"])
        @self.validate_json_request()
        @self.swagger_from("swagger_docs/face_features/visualize_face_bboxes.yml")
        def api_visualize_face_bboxes():
            """根据人脸边界框数据生成可视化图像"""
            try:
                data = request.parsed_data
                bboxes = data.get("bboxes")
                width = data.get("width", 512)
                height = data.get("height", 512)
                line_thickness = data.get("line_thickness", 2)

                # 验证参数
                if not bboxes or not isinstance(bboxes, list):
                    return create_error_response(400, "参数bboxes必须是一个非空数组")

                if not isinstance(width, int) or width <= 0:
                    return create_error_response(400, "参数width必须是一个正整数")

                if not isinstance(height, int) or height <= 0:
                    return create_error_response(400, "参数height必须是一个正整数")

                if not isinstance(line_thickness, int) or line_thickness <= 0:
                    return create_error_response(
                        400, "参数line_thickness必须是一个正整数"
                    )

                # 验证每个bbox的格式
                for i, bbox in enumerate(bboxes):
                    if not isinstance(bbox, list) or len(bbox) < 4:
                        return create_error_response(
                            400,
                            f"第{i + 1}个边界框格式错误，应为[x1, y1, x2, y2]或[x1, y1, x2, y2, score]",
                        )
                    try:
                        # 尝试转换为数字
                        [float(x) for x in bbox[:4]]
                    except (ValueError, TypeError):
                        return create_error_response(
                            400, f"第{i + 1}个边界框包含非数字值"
                        )

                # 调用FaceFeatureExtractor的可视化方法
                result = self.extractor.visualize_bboxes(
                    bboxes=bboxes,
                    width=width,
                    height=height,
                    line_thickness=line_thickness,
                )
                return create_success_response("边界框可视化成功", result)

            except Exception as e:
                return create_error_response(
                    500, f"生成边界框可视化图像时出错: {str(e)}"
                )

        @self.route("/extract_face_features", methods=["POST"])
        @self.validate_json_request()
        @self.swagger_from("swagger_docs/face_features/extract_face_features.yml")
        def api_extract_face_features():
            try:
                data = request.parsed_data
                self.logger.info(f"接收到长度为{len(data)}的请求数据")

                image_base64 = data.get("image_base64")
                det_thresh = data.get("det_thresh", 0.5)
                if not image_base64:
                    return create_error_response(
                        400,
                        "参数image_base64的值为空，请提供有效的base64编码的图片数据",
                    )

                # 验证base64格式
                try:
                    # 解码 base64 图片数据
                    image_data = base64.b64decode(image_base64)
                    nparr = np.frombuffer(image_data, np.uint8)
                    img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

                    if img is None:
                        return create_error_response(
                            400, "base64解码后的图片数据无效，请检查图片数据是否正确"
                        )

                except Exception as e:
                    return create_error_response(
                        400, f"base64解码失败，请检查图片数据是否正确: {str(e)}"
                    )

                # 使用唯一标识符创建临时文件名
                unique_id = uuid.uuid4()
                temp_image_path = f"temp_image_{unique_id}.jpg"
                cv2.imwrite(temp_image_path, img)

                # 提取特征
                features = self.extractor.extract_features(
                    image_path=temp_image_path,
                    thresh=det_thresh,
                )

                # 检查特征提取结果
                if not features:
                    # 确保在返回错误前删除临时文件
                    if os.path.exists(temp_image_path):
                        os.remove(temp_image_path)
                    return create_error_response(422, "未能从图片中检测到人脸")

                # 删除临时图片
                os.remove(temp_image_path)

                # 返回标准化响应，根据人脸数量动态生成消息
                face_count = len(features)
                return create_success_response(
                    f"有{face_count}份人脸特征提取成功", features
                )

            except Exception as e:
                return create_error_response(500, f"服务器内部错误: {str(e)}")

        @self.route("/batch_extract_face_features", methods=["POST"])
        @self.validate_json_request()
        @self.swagger_from("swagger_docs/face_features/batch_extract_face_features.yml")
        def api_batch_extract_face_features():
            try:
                data = request.parsed_data
                images_base64_raw = data.get("images_base64", [])
                det_thresh = data.get("det_thresh", 0.5)

                # 验证请求格式
                if not isinstance(images_base64_raw, list):
                    return create_error_response(400, "参数images_base64必须是一个数组")

                # 尝试将原始数据转换为类型化的结构
                try:
                    images_base64: List[BatchExtractFaceFeaturesParam] = []
                    for item in images_base64_raw:
                        if (
                            not isinstance(item, dict)
                            or "image_name" not in item
                            or "image_base64" not in item
                        ):
                            return create_error_response(
                                400, "每个图片项必须包含image_name和image_base64字段"
                            )
                        images_base64.append(
                            {
                                "image_name": item["image_name"],
                                "image_base64": item["image_base64"],
                            }
                        )
                except Exception as e:
                    return create_error_response(400, f"请求数据格式错误: {str(e)}")

                if not images_base64:
                    return create_error_response(400, "参数images_base64不能为空数组")

                max_batch_size = global_config.get("insightface.max_batch_size", 100)

                if len(images_base64) > max_batch_size:
                    return create_error_response(
                        400,
                        f"一次请求最多处理{max_batch_size}张图片，当前请求包含{len(images_base64)}张图片",
                    )

                results: List[BatchImageResult] = []
                success_count = 0
                failed_count = 0

                for index, image_data in enumerate(images_base64):
                    image_name = image_data["image_name"]
                    image_base64 = image_data["image_base64"]

                    if not image_base64:
                        result: BatchImageResult = {
                            "image_index": index,
                            "image_name": image_name,
                            "success": False,
                            "error": "图片base64编码为空",
                            "face_count": None,
                            "features": [],
                        }
                        results.append(result)
                        failed_count += 1
                        continue

                    try:
                        # 解码 base64 图片数据
                        decoded_data = base64.b64decode(image_base64)
                        nparr = np.frombuffer(decoded_data, np.uint8)
                        img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

                        if img is None:
                            result: BatchImageResult = {
                                "image_index": index,
                                "image_name": image_name,
                                "success": False,
                                "error": "base64解码后的图片数据无效",
                                "face_count": None,
                                "features": [],
                            }
                            results.append(result)
                            failed_count += 1
                            continue

                    except Exception as e:
                        result: BatchImageResult = {
                            "image_index": index,
                            "image_name": image_name,
                            "success": False,
                            "error": f"base64解码失败: {str(e)}",
                            "face_count": None,
                            "features": [],
                        }
                        results.append(result)
                        failed_count += 1
                        continue

                    # 保存临时图片
                    # 使用唯一标识符创建临时文件名
                    unique_id = uuid.uuid4()
                    temp_image_path = f"temp_image_{index}_{unique_id}.jpg"
                    cv2.imwrite(temp_image_path, img)

                    # 提取特征
                    features = self.extractor.extract_features(
                        image_path=temp_image_path, thresh=det_thresh
                    )

                    # 删除临时图片
                    os.remove(temp_image_path)

                    if not features:
                        result: BatchImageResult = {
                            "image_index": index,
                            "image_name": image_name,
                            "success": False,
                            "error": "未能从图片中检测到人脸",
                            "face_count": 0,
                            "features": [],
                        }
                        results.append(result)
                        failed_count += 1
                    else:
                        # 为每个人脸特征添加图片名称
                        for feature in features:
                            feature["image_name"] = image_name

                        result: BatchImageResult = {
                            "image_index": index,
                            "image_name": image_name,
                            "success": True,
                            "error": None,
                            "face_count": len(features),
                            "features": features,
                        }
                        results.append(result)
                        success_count += 1

                # 返回批处理结果
                batch_result: BatchProcessResult = {
                    "total": len(images_base64),
                    "success_count": success_count,
                    "failed_count": failed_count,
                    "results": results,
                }

                return create_success_response(
                    f"批量处理完成，共处理{len(images_base64)}张图片，成功{success_count}张，失败{failed_count}张",
                    batch_result,
                )

            except Exception as e:
                return create_error_response(500, f"服务器内部错误: {str(e)}")

        @self.route("/visualize_face_landmarks", methods=["POST"])
        @self.validate_json_request()
        @self.swagger_from("swagger_docs/face_features/visualize_face_landmarks.yml")
        def api_visualize_face_landmarks():
            """根据人脸landmark数据生成关键点可视化图像"""
            try:
                data = request.parsed_data
                landmarks_list = data.get("landmarks_list")
                width = data.get("width", 512)
                height = data.get("height", 512)
                point_radius = data.get("point_radius", 5)
                show_indices = data.get("show_indices", True)

                # 验证参数
                if not landmarks_list or not isinstance(landmarks_list, list):
                    return create_error_response(400, "参数landmarks必须是一个非空数组")

                if not isinstance(width, int) or width <= 0:
                    return create_error_response(400, "参数width必须是一个正整数")

                if not isinstance(height, int) or height <= 0:
                    return create_error_response(400, "参数height必须是一个正整数")

                # 调用FaceFeatureExtractor的可视化方法
                result = self.extractor.visualize_landmarks(
                    landmarks_list=landmarks_list,
                    width=width,
                    height=height,
                    point_radius=point_radius,
                    show_indices=show_indices,
                )
                return create_success_response("关键点可视化成功", result)

            except Exception as e:
                return create_error_response(
                    500, f"生成关键点可视化图像时出错: {str(e)}"
                )
